package Client.GUI;

import Client.*;
import Library.*;
import Library.Events.*;
import Library.Game.*;
import Client.Net.*;
import java.rmi.*;
import java.util.Map.*;
import javax.swing.*;
import Client.GUI.Controls.*;
import Client.GUI.Popups.*;
import Library.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.Timer;

public class pnlClientWorldMap extends javax.swing.JPanel implements IPopupContainer, IDisposable
{
    protected final transient Object m_ActivePopupMutex = new Object();
    protected transient AbstractPopup m_ActivePopup;
    
    protected transient ICommunication m_Communication;
    protected transient JWorldMapPanel m_WorldMap;
    
     ActionListener repaintAll = new ActionListener() {
        public void actionPerformed(ActionEvent evt)
        {            
             redrawPopup();
        }
    };   
    
    public void redrawPopup()
    {         
        try
        {
            synchronized (m_ActivePopupMutex)
            {
                if (m_ActivePopup != null)  
                {
                    m_ActivePopup.revalidate();
                    m_ActivePopup.repaint();             
                }
            }
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
    
    /** 
     * Creates new form pnlClientWorldMap 
     * @param communication callback to the upper Frame with ClientService.
     */
    public pnlClientWorldMap(ICommunication communication) throws RemoteException
    {
        initComponents();
        m_Communication = communication;
	
        m_WorldMap = new JWorldMapPanel("wereldkaart");
        m_WorldMap.addMouseListener(new java.awt.event.MouseAdapter()
        {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt)
            {
                jWorldMapClicked(evt);
            }
        });
        add(m_WorldMap);
        //formComponentResized(new java.awt.event.ComponentEvent(this, 0));
        
	// remove flickering from list
	lstPlayerList.setDoubleBuffered(true);
        new Timer(500, repaintAll).start();
        
	try
	{
	    setPlayers();
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}
	try
	{
	    register();
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}
    }
    
    private void register() throws Exception
    {
	m_Communication.getService().onArmiesPlaced.register(onArmiesPlaced);
	m_Communication.getService().onAttack.register(onAttack);
	m_Communication.getService().onGameStatusChanged.register(onGameStatusChanged);
	m_Communication.getService().onGameTimerEvent.register(onGameTimerEvent);
	m_Communication.getService().onGameTurnChanged.register(onGameTurnChanged);
	m_Communication.getService().onDefending.register(onDefending);
	m_Communication.getService().onMessage.register(onMessage);
	m_Communication.getService().onMoveArmies.register(onMoveArmies);
	m_Communication.getService().onPlacementTimerEvent.register(onPlacementTimerEvent);
	m_Communication.getService().onPlayerDecided.register(onPlayerDecided);
	m_Communication.getService().onPlayerLeft.register(onPlayerLeft);
	m_Communication.getService().onSetLandOwner.register(onSetLandOwner);
	m_Communication.getService().onTurnTimerEvent.register(onTurnTimerEvent);
	m_Communication.getService().onUpdateAvailableArmies.register(onUpdateAvailableArmies);
    }
    
    private void unregister()
    {
	m_Communication.getService().onArmiesPlaced.unregister(onArmiesPlaced);
	m_Communication.getService().onAttack.unregister(onAttack);
	m_Communication.getService().onGameStatusChanged.unregister(onGameStatusChanged);
	m_Communication.getService().onGameTimerEvent.unregister(onGameTimerEvent);
	m_Communication.getService().onGameTurnChanged.unregister(onGameTurnChanged);
	m_Communication.getService().onDefending.unregister(onDefending);
	m_Communication.getService().onMessage.unregister(onMessage);
	m_Communication.getService().onMoveArmies.unregister(onMoveArmies);
	m_Communication.getService().onPlacementTimerEvent.unregister(onPlacementTimerEvent);
	m_Communication.getService().onPlayerDecided.unregister(onPlayerDecided);
	m_Communication.getService().onPlayerLeft.unregister(onPlayerLeft);
	m_Communication.getService().onSetLandOwner.unregister(onSetLandOwner);
	m_Communication.getService().onTurnTimerEvent.unregister(onTurnTimerEvent);
	m_Communication.getService().onUpdateAvailableArmies.unregister(onUpdateAvailableArmies);
    }

    private void jWorldMapClicked(java.awt.event.MouseEvent evt)
    {
        LandInfo land = m_WorldMap.getLand(evt.getX(), evt.getY());
        if (land != null)
        {
	    try
	    {
		if (m_Communication.getService().getGame().getState() == GameState.GAME_SETUP ||
		    m_Communication.getService().getTurnDecission() == TurnDecission.Reinforce ||
		    m_Communication.getService().getTurnDecission() == TurnDecission.ReinforceBonus)
		{
		    // Reinforce land
		    if (!land.getOwner().getName().equals(m_Communication.getService().getTicket().getUsername()))
			Message("Cannot reinforce other player's lands.");
		    else
		    {
			int result = m_Communication.getService().reinforce(land.getID(), 1);
			if (result == ErrorCodes.ERROR_NOERROR)
			    Message("Reinforcing " + land.getName() + "..");
			else
			    Message("Cannot Reinforce " + land.getName() + " because " + ErrorCodes.getMessage(result));
		    }
		}
		else
		{
		    // Playing
		    if (m_Communication.getService().getTurnDecission() == TurnDecission.Attack)
		    {
			// Attacking
			if (m_WorldMap.getSelection2() != null)
			{
			    // Clear Selections
			    m_WorldMap.setSelection1(null);
			    m_WorldMap.setSelection2(null);
			    Message("Selection Cleared");
			}
			else if (m_WorldMap.getSelection1() == null)
			{
			    // Set Selection1
			    if (!land.getOwner().getName().equals(m_Communication.getService().getTicket().getUsername()))
				Message("You first must select a land to attack from which belongs to you.");
			    else
			    {
				m_WorldMap.setSelection1(land);
				Message("Selected " + land.getName() + " to attack from.");
			    }
			}
			else 
			{
			    LandInfo l1 = m_WorldMap.getSelection1();
			    if (l1 == land)
			    {
				// Selected the same lands, clear Selections
				m_WorldMap.setSelection1(null);
				m_WorldMap.setSelection2(null);
			    }
			    else
			    {
				// Set Selection2
				if (land.getOwner().getName().equals(m_Communication.getService().getTicket().getUsername()))
				    Message("You must select a land to attack which belongs to another player.");
				else
				{
				    m_WorldMap.setSelection2(land);
				    Message("Selected " + land.getName() + " to attack.");
				}
			    }
			}
			
			// Enable Attack Land Button if we have 2 Selected Lands
			if (m_WorldMap.getSelection2() != null)
			    btnAttackLand.setEnabled(true);
		    }
		    else
		    {
			Message("If it's your turn you have to choose to attack or reinforce first.");
		    }
		}
	    }
	    catch (RemoteException ex)
	    {
		ex.printStackTrace();
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
        }       
        
	//m_WorldMap.repaint();
        //invalidate();
	repaintObjects();
    }
    
    private final Object m_TextMutex = new Object();
    public void Message(String msg)
    {
	synchronized (m_TextMutex)
	{
	    try
	    {
		txtResultlist.append(msg + "\r\n");
		txtResultlist.getCaret().setDot(txtResultlist.getText().length());
		txtResultlist.scrollRectToVisible(txtResultlist.getVisibleRect());
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane2 = new javax.swing.JScrollPane();
        lstPlayerList = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtResultlist = new javax.swing.JTextArea();
        btnAttackLand = new javax.swing.JButton();
        btnReinforce = new javax.swing.JButton();
        pnlButtons = new javax.swing.JPanel();
        btnLeave = new javax.swing.JButton();
        lblTimeLeft = new javax.swing.JLabel();
        lblTimeText = new javax.swing.JLabel();
        lblRoundTimeLeft = new javax.swing.JLabel();
        lblRoundTimeText = new javax.swing.JLabel();
        lblAvailableReinforcements = new javax.swing.JLabel();
        btnEndAttack = new javax.swing.JButton();
        btnAttack = new javax.swing.JButton();
        btnEndTurn = new javax.swing.JButton();

        setPreferredSize(new java.awt.Dimension(1200, 750));
        addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        lstPlayerList.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] { },
            new String [] {
                "Player", "Lands", "Soldiers", "Color"
            }
        ));
        jScrollPane2.setViewportView(lstPlayerList);

        txtResultlist.setColumns(20);
        txtResultlist.setEditable(false);
        txtResultlist.setRows(5);
        jScrollPane1.setViewportView(txtResultlist);

        btnAttackLand.setText("Attack Land");
        btnAttackLand.setEnabled(false);
        btnAttackLand.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAttackLandActionPerformed(evt);
            }
        });

        btnReinforce.setText("Reinforce");
        btnReinforce.setEnabled(false);
        btnReinforce.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnReinforceActionPerformed(evt);
            }
        });

        btnLeave.setText("Leave Game");
        btnLeave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnLeaveActionPerformed(evt);
            }
        });

        lblTimeLeft.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
        lblTimeLeft.setText("Preparing..");

        lblTimeText.setText("GameTime Left:");

        lblRoundTimeLeft.setFont(new java.awt.Font("Tahoma", 1, 24));
        lblRoundTimeLeft.setText("Preparing..");

        lblRoundTimeText.setText("RoundTime Left:");

        javax.swing.GroupLayout pnlButtonsLayout = new javax.swing.GroupLayout(pnlButtons);
        pnlButtons.setLayout(pnlButtonsLayout);
        pnlButtonsLayout.setHorizontalGroup(
            pnlButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlButtonsLayout.createSequentialGroup()
                .addGap(20, 20, 20)
                .addGroup(pnlButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lblTimeLeft)
                    .addComponent(lblRoundTimeText)
                    .addComponent(lblRoundTimeLeft)
                    .addComponent(lblTimeText)
                    .addComponent(btnLeave, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))
                .addContainerGap())
        );
        pnlButtonsLayout.setVerticalGroup(
            pnlButtonsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlButtonsLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(lblTimeText)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblTimeLeft, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(lblRoundTimeText)
                .addGap(4, 4, 4)
                .addComponent(lblRoundTimeLeft)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 13, Short.MAX_VALUE)
                .addComponent(btnLeave)
                .addContainerGap())
        );

        lblAvailableReinforcements.setFont(new java.awt.Font("Tahoma", 1, 14));
        lblAvailableReinforcements.setText("Available Reinforcements: ?");

        btnEndAttack.setText("Place Reinforcements and Attack.");
        btnEndAttack.setEnabled(false);
        btnEndAttack.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEndAttackActionPerformed(evt);
            }
        });

        btnAttack.setText("Attack");
        btnAttack.setEnabled(false);
        btnAttack.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnAttackActionPerformed(evt);
            }
        });

        btnEndTurn.setText("End Turn");
        btnEndTurn.setEnabled(false);
        btnEndTurn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEndTurnActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                        .addComponent(btnAttack)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnReinforce)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnAttackLand)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(btnEndAttack)
                        .addGap(18, 18, 18)
                        .addComponent(btnEndTurn, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(100, 100, 100))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 706, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(lblAvailableReinforcements)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 517, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(pnlButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(302, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addComponent(lblAvailableReinforcements)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(btnReinforce)
                            .addComponent(btnAttackLand)
                            .addComponent(btnEndAttack)
                            .addComponent(btnEndTurn)
                            .addComponent(btnAttack))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 142, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(pnlButtons, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap())
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 221, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(38, 38, 38))))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 486, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(26, 26, 26))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void btnEndTurnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEndTurnActionPerformed
        try
        {
            m_Communication.getService().endTurn();
            lblTimeLeft.setVisible(true);
            btnEndTurn.setVisible(true);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid Number", 0);
        }
    }//GEN-LAST:event_btnEndTurnActionPerformed

    private void btnLeaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLeaveActionPerformed
        try
        {
            Object[] options = new Object[]
            {
                "Yes, Leave Game!",
                "No, I want to keep playing!"
            };
            int choice = JOptionPane.showOptionDialog(this, 
                    "Do you really want to leave this game?", 
                    "Leave Game", 
                    JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, 
                    null, options, options[0]);
            if (choice == 0)
	    {
                m_Communication.getService().leaveGame();
		unregister();
                // Go back to GameList
                m_Communication.SetContent(new pnlGameList(m_Communication));
	    }
        }
        catch (RemoteException ex)
        {
            ex.printStackTrace();
            Message(ex.getMessage());
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            Message(ex.getMessage());
        }
        
    }//GEN-LAST:event_btnLeaveActionPerformed

    private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
        
    }//GEN-LAST:event_formComponentResized

    private void btnReinforceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnReinforceActionPerformed
	try
	{
	    int result = m_Communication.getService().turnDecission(TurnDecission.Reinforce);
	    if (result == ErrorCodes.ERROR_NOERROR)
	    {
		btnAttack.setEnabled(false);
		btnReinforce.setEnabled(false);
		btnAttackLand.setEnabled(false);
		btnEndTurn.setEnabled(true);
		btnEndAttack.setEnabled(false);
	    }
	    else
		JOptionPane.showConfirmDialog(this, ErrorCodes.getMessage(result), "Error During Deciding", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}
    }//GEN-LAST:event_btnReinforceActionPerformed

    public void disposePopups()
    {
	synchronized (m_ActivePopupMutex)
	{
	    if (m_ActivePopup != null)
	    {
		m_ActivePopup.dispose();
		m_ActivePopup = null;
	    }
	}
	repaint();
	invalidate();
	revalidate();
    }
    
    public void switchPopup(AbstractPopup popup)
    {
        try
        {
	synchronized (m_ActivePopupMutex)
	{
            if(m_ActivePopup != null)
            {
                if(m_ActivePopup != popup)
                {
                    m_ActivePopup.dispose();
                }
            }
	    m_ActivePopup = popup;
	    m_ActivePopup.showPopup(this);

            }
        }
        catch(Exception ex)
        {
            String p = ex.getMessage();
        }
    }
    
    private void btnAttackLandActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAttackLandActionPerformed
	switchPopup(new popAttack(m_Communication, this, m_WorldMap.getSelection1(), m_WorldMap.getSelection2()));
    }//GEN-LAST:event_btnAttackLandActionPerformed

    private void btnEndAttackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEndAttackActionPerformed
	try
	{
	    int result = m_Communication.getService().turnDecission(TurnDecission.ReinforceBonus);
	    if (result != ErrorCodes.ERROR_NOERROR)
		Message(ErrorCodes.getMessage(result));
	    else
		btnAttack.setEnabled(true);
		btnReinforce.setEnabled(false);
		btnAttackLand.setEnabled(false);
		btnEndTurn.setEnabled(true);
		btnEndAttack.setEnabled(false);
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}
    }//GEN-LAST:event_btnEndAttackActionPerformed

    private void btnAttackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAttackActionPerformed
	try
	{
            //in geval van actie placereinforcement and attack eerst de beurt keuze weer ongedaan maken
            System.out.println(m_Communication.getService().getTurnDecission());
          
	    int result = m_Communication.getService().turnDecission(TurnDecission.Attack);
	    if (result == ErrorCodes.ERROR_NOERROR)
	    {
		btnAttack.setEnabled(false);
		btnReinforce.setEnabled(false);
		btnAttackLand.setEnabled(true);
		btnEndTurn.setEnabled(true);
		btnEndAttack.setEnabled(false);
	    }
	    else
		JOptionPane.showConfirmDialog(this, ErrorCodes.getMessage(result), "Error During Deciding", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
	}
	catch (Exception ex)
	{
	    ex.printStackTrace();
	}
    }//GEN-LAST:event_btnAttackActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnAttack;
    private javax.swing.JButton btnAttackLand;
    private javax.swing.JButton btnEndAttack;
    private javax.swing.JButton btnEndTurn;
    private javax.swing.JButton btnLeave;
    private javax.swing.JButton btnReinforce;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel lblAvailableReinforcements;
    private javax.swing.JLabel lblRoundTimeLeft;
    private javax.swing.JLabel lblRoundTimeText;
    private javax.swing.JLabel lblTimeLeft;
    private javax.swing.JLabel lblTimeText;
    private javax.swing.JTable lstPlayerList;
    private javax.swing.JPanel pnlButtons;
    private javax.swing.JTextArea txtResultlist;
    // End of variables declaration//GEN-END:variables

    protected ActionListener onGameStatusChanged = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		ValueEvent<Integer> ev = (ValueEvent<Integer>)e;
		int status = ev.getValue().intValue();
	    	System.out.println("status game is " + GameState.getName(status));
		System.out.println("I'm client " + m_Communication.getService().getTicket().getUsername());
		Message("Game Status Changed to '" + GameState.getName(status) + "'.");
              
		
		if (status == GameState.GAME_STOPPED)
		{
		    //JOptionPane.showMessageDialog(null, "LAAT NU SCORESCREEN ZIEN", "GAME STOPPED/FINISHED", JOptionPane.ERROR_MESSAGE);
		    switchPopup(new popWin(m_Communication, self()));       
                   //m_ActivePopup.repaint();
                   
                    // LET OP: lijst met woordjes werkt niet hier; dus ergens anders typen en hierin plakken!!!!!!
		}
		
//		if (status != GameState.GAME_WAITINGFORPLAYERS)
//		{
//		    // De Host is de game gestart; pnlLobby moet verborgen worden
//		    try
//		    {
//			if (m_Communication.getContent() != this)
//			{
//			    m_Communication.SetContent(this);
//			    setPlayers(m_Communication.getService().getPlayers());
//			}
//		    }
//		    catch (RemoteException ex)
//		    {
//			ex.printStackTrace();
//		    }
//		    catch (Exception ex)
//		    {
//			ex.printStackTrace();
//		    }
//		}
	    }
	    catch(Exception ex)
	    {
		 System.out.println(ex.getMessage() + " " + ex.getStackTrace());           
	    }

	    // Just in case..
	    //m_WorldMap.repaint();
	    //invalidate();

	    repaintObjects();            
	}
    };

    private void repaintObjects()
    {
	if (m_WorldMap != null)
        {
            setComponentZOrder(m_WorldMap,2);
            System.out.println("repaint world "+ getComponentZOrder(m_WorldMap));
	    m_WorldMap.repaint();
        }

	if (m_ActivePopup != null)
        { 
            setComponentZOrder(m_ActivePopup,1);
            System.out.println("repaint popup"+ getComponentZOrder(m_ActivePopup));
	    m_ActivePopup.repaint();
            m_ActivePopup.revalidate();

        }
                   
        try
	{
            setPlayers();
        }
	catch (RemoteException ex)
	{
            ex.printStackTrace();
        }
	catch (Exception ex)
	{
            ex.printStackTrace();
        }
    } 
         
    protected pnlClientWorldMap self()
    {
	return this;
    }

    protected ActionListener onMessage = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		ValueEvent<String> ev = (ValueEvent<String>)e;
		Message(ev.getValue() + "\n");
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected ActionListener onGameTurnChanged = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		ValueEvent<IPlayer> ev = (ValueEvent<IPlayer>)e;
		IPlayer player = ev.getValue();
		disposePopups();
		Message("Player '" + player.getName() + "' must attack or place armies.");

		m_WorldMap.setSelection1(null);
		m_WorldMap.setSelection2(null);

		// Set Round Timer Color to Player Color
		lblRoundTimeLeft.setForeground(PlayerColor.getColor(player.getColor()));

		// Ben ik aan de beurt?
		if (m_Communication.getService().getTicket().getUsername().equals(player.getName()))
		{
		    btnAttack.setEnabled(true);
		    btnReinforce.setEnabled(true);
		    btnAttackLand.setEnabled(false);
		    btnEndTurn.setEnabled(false);
                    
                    if (m_BonusAmount > 0)
                    {
                        btnEndAttack.setEnabled(true);
                    }
                    else 
                    {
                        btnEndAttack.setEnabled(false);
                    }

		}
		else
		{
		    btnAttack.setEnabled(false);
		    btnReinforce.setEnabled(false);
		    btnAttackLand.setEnabled(false);
		    btnEndTurn.setEnabled(false);
		    btnEndAttack.setEnabled(false);
		}
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    
    protected ActionListener onMoveArmies = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		MoveEvent ev = (MoveEvent)e;
		//TODO:add code onmovearmies
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };


    protected ActionListener onAttack = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		AttackEvent ev = (AttackEvent)e;
		IPlayer attPlayer = ev.getAttacker();
		int attLandId = ev.getAttackerLandID();
		List<Integer> attDices = ev.getAttackerDices();
		int lostAttArmies = ev.getAttackerLost();
		IPlayer defPlayer = ev.getDefender();
		int defLandId = ev.getDefenderLandID();
		List<Integer> defDices = ev.getDefenderDices();
		int lostDefArmies = ev.getDefenderLost();
		boolean attacker = attPlayer.getName().equals(m_Communication.getService().getTicket().getUsername());
		boolean defender = defPlayer.getName().equals(m_Communication.getService().getTicket().getUsername());
		LandInfo attLand = m_WorldMap.getLand(attLandId);
		LandInfo defLand = m_WorldMap.getLand(defLandId);
                LandInfo m_AttackingLand = attLand;
                LandInfo m_DefendingLand = defLand;

                // Show results:

		if (attacker || defender)
		    switchPopup(new popAttackResult(m_Communication, self(),
			    attLand, attDices, lostAttArmies,
			    defLand, defDices, lostDefArmies,
			    attPlayer, defPlayer, attacker));

		// Update WorldMap:
              if (defLand.getAmountOfArmies()- lostDefArmies  <= 0)
		{
		    // Victorious
                    System.out.println("victorious " + defLand.getOwner().getName());
                    System.out.println("def " + defLand.getAmountOfArmies());
                    System.out.println("att " + attLand.getAmountOfArmies());
		    defLand.setOwner(attPlayer);
                    if((attLand.getAmountOfArmies() - lostAttArmies )< attDices.size()){
                        System.out.println("klein"+attLand.getAmountOfArmies());
                        defLand.setAmountOfArmies(attLand.getAmountOfArmies() - lostAttArmies-1);
                        attLand.setAmountOfArmies(1);
                    }
                    else {
                        defLand.setAmountOfArmies(attDices.size());
		    attLand.setAmountOfArmies(attLand.getAmountOfArmies() - lostAttArmies - attDices.size());
                    System.out.println("groot"+attLand.getAmountOfArmies());
                    }
		    
		    // Show results in Messages:
		    Message(attLand.getName() + "(" + attPlayer.getName() + "," + PlayerColor.getColorName(attPlayer.getColor()) + ","  + lostAttArmies + " soldiers lost) attacked " +
			    defLand.getName() + "(" + defPlayer.getName() + "," + PlayerColor.getColorName(defPlayer.getColor()) + ","  + lostDefArmies + " soldiers lost) and was victorious!");

		}
		else
		{
		    // Non-Victorious
                    System.out.println("Non-victorious " + defLand.getOwner().getName());
                    System.out.println("def " + defLand.getAmountOfArmies());
                    System.out.println("att " + attLand.getAmountOfArmies());
		    attLand.setAmountOfArmies(attLand.getAmountOfArmies() - lostAttArmies);
		    defLand.setAmountOfArmies(defLand.getAmountOfArmies() - lostDefArmies);

		    // Show results in Messages:
		    Message(attLand.getName() + "(" + attPlayer.getName() + "," + PlayerColor.getColorName(attPlayer.getColor()) + ","  + lostAttArmies + " soldiers lost) attacked " +
			    defLand.getName() + "(" + defPlayer.getName() + "," + PlayerColor.getColorName(defPlayer.getColor()) + ","  + lostDefArmies + " soldiers lost)!");
		}
         repaintObjects();
		
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };
    
    /**
     * Zet Players in de PlayerList en geeft deze hun kleur.
     * @param players 
     */
    public void setPlayers() throws RemoteException, Exception
    {
        List<LandInfo> m_Landen = m_WorldMap.getLanden();
        List<IPlayer> players = m_Communication.getService().getPlayers();
        try  
        {   
            //ColoredTableCell renderer = new ColoredTableCell("Player");
            //lstPlayerList.getColumnModel().getColumn(0).setCellRenderer(renderer);
            javax.swing.table.DefaultTableModel mdl = (javax.swing.table.DefaultTableModel)lstPlayerList.getModel();
            if (mdl.getRowCount() > 0)
            {
                 while(mdl.getRowCount() > 0)
                 {
                     mdl.removeRow(0);
                 }
            }

            Iterator<IPlayer> it = players.iterator();
            while (it.hasNext())
            {    int countland = 0;
                 int countleger = 0;
                IPlayer cur = it.next();
                Iterator<LandInfo> itl = m_Landen.iterator();
                while (itl.hasNext())
                {
                    LandInfo curent = itl.next();
                   //System.out.println("CURENT " +curent.m_Player.getName() + " CUR "+ cur.getName());
                    if (curent.m_Player!= null){


                    if( curent.m_Player.getName().equals(cur.getName()))
                    {
                        countland++;
                        countleger = countleger + curent.getAmountOfArmies();
                    }
                    }
                }
                //renderer.setBackground(PlayerColor.getColor(cur.getColor()));

                
                mdl.addRow(new Object[] {  cur.getName(), countland, countleger, PlayerColor.getColorName(cur.getColor()) });

            }
        }
        catch (RemoteException ex)
        {
            ex.printStackTrace();
        }
    }

    /**
     * Callback methode die wordt aangeroepen door de server tijdens het initializeren van het spel.
     * Deze wordt getriggered als een land is toegewezen aan een speler.
     * @param landId
     * @param plr
     * @throws RemoteException
     * @throws Exception 
     */
    protected ActionListener onSetLandOwner = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		LandOwnerEvent ev = (LandOwnerEvent)e;
		LandInfo land = m_WorldMap.getLand(ev.getLandID());
		land.setOwner(ev.getPlayer());
		land.setAmountOfArmies(1);
                System.out.println("onsetlandowner" + land.getName()+" "+land.getAmountOfArmies() );
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };


    protected ActionListener onPlayerDecided = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		DecissionEvent ev = (DecissionEvent)e;
		Message("Player: " + ev.getPlayer().getName() + " decides to " + TurnDecission.getText(ev.getDecission()) + ".");
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected ActionListener onPlacementTimerEvent = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		TimeEvent ev = (TimeEvent)e;
		int time = ev.getTime();
		int totaltime = ev.getTotalTime();
		lblTimeText.setText("SetupTime Left:");
		int hrs = time / 3600;
		int temp = time - (3600 * hrs);
		int mins = temp / 60;
		int secs = temp - (mins * 60);
		lblTimeLeft.setText(String.format("%02d:%02d:%02d", hrs, mins, secs));
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };
    
    protected ActionListener onTurnTimerEvent = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		TimeEvent ev = (TimeEvent)e;
		int time = ev.getTime();
		int totaltime = ev.getTotalTime();
		int hrs = time / 3600;
		int temp = time - (3600 * hrs);
		int mins = temp / 60;
		int secs = temp - (mins * 60);
		lblRoundTimeLeft.setText(String.format("%02d:%02d:%02d", hrs, mins, secs));
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected ActionListener onGameTimerEvent = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		TimeEvent ev = (TimeEvent)e;
		int time = ev.getTime();
		int totaltime = ev.getTotalTime();
		lblTimeText.setText("GameTime Left:");
		int hrs = time / 3600;
		int temp = time - (3600 * hrs);
		int mins = temp / 60;
		int secs = temp - (mins * 60);
		lblTimeLeft.setText(String.format("%02d:%02d:%02d", hrs, mins, secs));
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };
    
    /**
     * Event dat wordt getriggerd als een speler nieuwe legers erbij krijgt of verlies.
     * @param player speler wie het overkomt
     * @param landID land waar het overkomt
     * @param totalArmies totaal nadat dit overkomen is
     * @param newArmies aantal in delta
     * @throws RemoteException
     * @throws Exception 
     */
    protected ActionListener onArmiesPlaced = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		ArmyPlacementEvent ev = (ArmyPlacementEvent)e;
		IPlayer player = ev.getPlayer();
		int landID = ev.getLandID();
		int totalArmies = ev.getTotalArmies();
		int newArmies = ev.getNewArmies();
		LandInfo land = m_WorldMap.getLand(landID);
		if (newArmies < 0)
		    Message("Player " + player.getName() + " lost " + newArmies + " armies in " + land.getName() + " and has now " + totalArmies + " armies.\n");
		else
		    Message("Player " + player.getName() + " gained " + newArmies + " armies in " + land.getName() + " and has now " + totalArmies + " armies.\n");
		land.setAmountOfArmies(totalArmies);

		//m_WorldMap.repaint();
		//invalidate();
		repaintObjects();
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected int m_Amount;
    protected int m_BonusAmount;
    protected ActionListener onUpdateAvailableArmies = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		ArmySizeEvent ev = (ArmySizeEvent)e;
		lblAvailableReinforcements.setText("Available Reinforcements: " + ev.getArmies() + " " + ev.getBonusArmies() + " bonus.");
		m_Amount = ev.getArmies();
		m_BonusAmount = ev.getBonusArmies();
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected ActionListener onDefending = new ActionListener()
    {
	@Override
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		DefensiveEvent ev = (DefensiveEvent)e;
		IPlayer attacker = ev.getAttacker();
		int attLandID = ev.getAttackerLandID();
		int amount = ev.getAmount();
		int defLandID = ev.getDefenderLandID();
		int reqDefAmount = ev.getRecommendedDefensiveArmies();
		
		LandInfo attLand = m_WorldMap.getLand(attLandID);
		LandInfo defLand = m_WorldMap.getLand(defLandID);
		switchPopup(new popDefend(m_Communication, self(), attLand, defLand, amount, reqDefAmount));
                repaintObjects();
            }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };

    protected ActionListener onPlayerLeft = new ActionListener()
    {
	public void actionPerformed(ActionEvent e)
	{
	    try
	    {
		repaintObjects();
		//setPlayers();
	    }
	    catch (Exception ex)
	    {
		ex.printStackTrace();
	    }
	}
    };
    
    public void dispose()
    {
	unregister();
    }
}
